/*
 * Created on 2006-12-6
 *
 */
package jacky.lanlan.song.extension.spring.aop;

import java.util.*;

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.Ordered;

/**
 * @author 宋兰岚 AOP拦截器，把null返回值转换为对应的NullObject对象(如果可能的话)
 */
@Aspect
public class ReturnNullObjectAdvisor implements Ordered {
	private Logger logger=Logger.getLogger(ReturnNullObjectAdvisor.class);
	private int order = 1;
	
	public int getOrder() {
		return order;
	}

	public void setOrder(int order) {
		this.order = order;
	}
	
	// //////////////////Advice 定义////////////////////
	
	/**
	 * AOP拦截实现 Null Object 设计模式。
	 * <p>
	 * 针对所有标注了ReturnNullObject的方法(使用 Null Object 模式的方法)，当
	 * 这些方法返回了null值的时候，这个Advice把null变成适合该方法的NullObject 对象。这样业务代码就不用处理 NullPointerException 了。
	 * <p>
	 * 注意，因为需要影响返回值，所以这里的拦截器必须是<code><em>around advice</em></code> 而不能是
	 * <code>after returning advice</code>，因为后者无法影响到连接点的返回值。
	 * 
	 * @param pjp
	 *          连接点处理过程
	 * @return 适合于JoinPoint的Null Object
	 */
	@Around(
			"@annotation(jacky.lanlan.song.extension.spring.aop.annotation.ReturnNullObject) ||" + // 侦测方法声明上的标注
			"@within(jacky.lanlan.song.extension.spring.aop.annotation.ReturnNullObject)"// 侦测类声明上的标注
			)
	public Object turnNullToNullObject(ProceedingJoinPoint pjp) {
		Object reValue=null;
		try {
			reValue=pjp.proceed();
		}
		catch (Throwable e) {
			if(logger.isDebugEnabled()) {
				logger.error("拦截调用 [" + pjp.getSignature().toLongString().split("\\s")[3] + "] 时出错", e);
			}
		}
		
		if(reValue==null) {
			String[] signature = pjp.getSignature().toLongString().split("\\s");// 得到JoinPoint的签名
			// 第3个元素(signature[2])是返回类型，所以...
			// 对于集合类型
			if (signature[2].contains("List")) {// 如果是List，则生成一个空List，下面类似
				return reValue=Collections.EMPTY_LIST;
			}
			if(signature[2].contains("Map")) {
				return reValue=Collections.EMPTY_MAP;
			}
			if(signature[2].contains("Queue")) {
				return reValue=new LinkedList<Object>();
			}
			if(signature[2].contains("Set")) {
				return reValue=Collections.EMPTY_SET;
			}
			
			// 其他任意类型
			try {
				Class<?> returnType=Class.forName(signature[2]);
				if (!returnType.isInterface() && !returnType.isPrimitive()) {// 非接口非primitive
					reValue = returnType.newInstance();// 动态创建这个类型的一个新对象
				}
			}
			catch (ClassNotFoundException e) {}
			catch (InstantiationException e) {}
			catch (IllegalAccessException e) {}
		}
		
		return reValue;
	}

}
